//======================================================================
//
//	HDRSample
//
//		by MJP
//		09/20/08
//
//======================================================================
//
//	File:		Model.fx
//
//	Desc:		Renders the scene model, applying a single directional
//				light source.
//
//======================================================================

#include "LogLuv.fxh"

// Transform matrices
float4x4 g_matWorld;
float4x4 g_matView;
float4x4 g_matProj;

// Camera position
float3 g_vCameraPositionWS;

// Lighting parameters
float3 g_vSunlightDirectionWS;
float3 g_vSunlightColor;
float g_fSunlightBrightness;

// Material parameters
float3 g_vDiffuseAlbedo;
float3 g_vSpecularAlbedo; 
float g_fSpecularPower;
float g_fReflectivity;

float g_fReflectionBrightness;

texture ReflectionMap;
samplerCUBE ReflectionSampler = sampler_state
{
    Texture = <ReflectionMap>;
    MinFilter = anisotropic;
    MagFilter = linear;
    MipFilter = linear;
    AddressU = Clamp;
    AddressV = Clamp;
    AddressW = Clamp;
    MaxAnisotropy = 16;
};

// Calculated the contribution for a single light
float3 CalcLighting (	float3 vDiffuseAlbedo, 
						float3 vSpecularAlbedo, 
						float fSpecularPower, 
						float3 vLightColor, 
						float3 vNormal, 
						float3 vLightDir, 
						float3 vViewDir	)
{
	float3 R = normalize(reflect(-vLightDir, vNormal));
    
    // Calculate the raw lighting terms
    float fDiffuseReflectance = saturate(dot(vNormal, vLightDir));
    float fSpecularReflectance = saturate(dot(R, vViewDir));

	// Modulate the lighting terms based on the material colors, and the attenuation factor
    float3 vSpecular = vSpecularAlbedo * vLightColor * pow(fSpecularReflectance, fSpecularPower);
    float3 vDiffuse = vDiffuseAlbedo * vLightColor * fDiffuseReflectance;	

	// Lighting contribution is the sum of diffuse and specular terms
	return vDiffuse + vSpecular;
}

// Vertex shader
void ModelVS (	in float4 in_vPositionOS	: POSITION,
				in float3 in_vNormalOS		: NORMAL,
				out float4 out_vPositionCS	: POSITION,
				out float3 out_vNormalWS	: TEXCOORD0,
				out float3 out_vPositionWS	: TEXCOORD1	)
{
	// Calculate the clip-space vertex position
	float4x4 matWorldViewProj = mul(mul(g_matWorld, g_matView), g_matProj);
	out_vPositionCS = mul(in_vPositionOS, matWorldViewProj);

	// Calculate world-space position and normal
	out_vPositionWS = mul(in_vPositionOS, g_matWorld);
	out_vNormalWS = mul(in_vNormalOS, g_matWorld);
}				

// Pixel shader
float4 ModelPS (	in float3 in_vNormalWS		: TEXCOORD0,
					in float3 in_vPositionWS	: TEXCOORD1,
					uniform bool bEncodeLogLuv	) : COLOR0
{
	// Calculate the reflected view direction
	float3 vNormalWS = normalize(in_vNormalWS);
	float3 vViewDirWS = normalize(g_vCameraPositionWS - in_vPositionWS);
	float3 vReflectedDirWS = reflect(-vViewDirWS, vNormalWS);
	vReflectedDirWS.z *= -1;
	
	// Get the sunlight term
	float3 vColor = CalcLighting(	g_vDiffuseAlbedo,
									g_vSpecularAlbedo,
									g_fSpecularPower,
									g_vSunlightColor * g_fSunlightBrightness,
									vNormalWS,
									normalize(-g_vSunlightDirectionWS),
									vViewDirWS	);
									
	// Add in the reflection
	float3 vReflection = texCUBE(ReflectionSampler, vReflectedDirWS);
	vColor += vReflection * g_fReflectivity * g_fReflectionBrightness;																			
	
	// Encode to LogLuv?
	float4 vOutput;
	if (bEncodeLogLuv)
		vOutput = LogLuvEncode(vColor);
	else
		vOutput = float4(vColor, 1.0f);							

	// return the color
	return vOutput;
}


technique Render
{
    pass p0
    {
		ZEnable = true;
		ZWriteEnable = true;
		AlphaBlendEnable = false;
		CullMode = CCW;
		AlphaTestEnable = false;
		StencilEnable = false;
    
        VertexShader = compile vs_2_0 ModelVS();
        PixelShader = compile ps_2_0 ModelPS(false);
    }
}

technique RenderEncode
{
    pass p0
    {
		ZEnable = true;
		ZWriteEnable = true;
		AlphaBlendEnable = false;
		CullMode = CCW;
		AlphaTestEnable = false;
		StencilEnable = false;	
    
        VertexShader = compile vs_2_0 ModelVS();
        PixelShader = compile ps_2_0 ModelPS(true);
    }
}				